﻿using Abp.AspNetCore;
using Abp.Castle.Logging.NLog;
using Abp.Dependency;
using Batman.Cache.Extensions;
using Batman.Cms.Core.Commands;
using Batman.Jianbei.Forum.Config;
using Batman.Jianbei.Forum.Core.Consts;
using Batman.Jianbei.Forum.Core.Datas;
using Batman.Jianbei.Forum.Core.Domains;
using Batman.Jianbei.Forum.SignalR;
using Batman.Jianbei.Forum.SimpleMaintenance;
using Batman.Maintenance;
using Castle.Facilities.Logging;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Senparc.CO2NET;
using Senparc.CO2NET.RegisterServices;
using Senparc.Weixin;
using Senparc.Weixin.Entities;
using Senparc.Weixin.RegisterServices;
using SixLabors.ImageSharp.Web.Caching;
using SixLabors.ImageSharp.Web.Commands;
using SixLabors.ImageSharp.Web.DependencyInjection;
using SixLabors.ImageSharp.Web.Processors;
using SixLabors.ImageSharp.Web.Providers;
using SixLabors.Memory;
using System;
using System.Text;

namespace Batman.Jianbei.Forum
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            #region 配置Identity

            // 从配置中获取数据库连接串
            var connectionStr = Configuration.GetConnectionString("Default");
            services.AddDbContext<JianbeiForumDbContext>(options => options.UseMySql(connectionStr));

            // 加Identity会让JwtToken失效
            //services.AddIdentity<User, IdentityRole>()
            //        .AddEntityFrameworkStores<JianbeiForumDbContext>();

            services.AddIdentityCore<User>().AddEntityFrameworkStores<JianbeiForumDbContext>();

            services.TryAddScoped<SignInManager<User>>(); // 需要加，不然abp也无法加入IocManager


            // TODO: 初始化数据库的用户数据等

            #endregion

            #region 配置jwtbearer

            Action<JwtBearerOptions> configureOptions = options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidAudience = JwtBearerSetting.valid_audience,
                    ValidIssuer = JwtBearerSetting.valid_issuer,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtBearerSetting.secret))
                };
            };

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(configureOptions)
                    // Microsoft.AspNetCore.Identity SignInManager需要
                    .AddCookie("Identity.Application");

            #endregion

            #region 微信senparc配置

            services.AddSenparcGlobalServices(Configuration)
                    .AddSenparcWeixinServices(Configuration);

            #endregion

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSignalRCore();
            services.AddSignalR();

            services.AddImageSharpCore(options =>
            {
            })
                .SetRequestParser<QueryCollectionRequestParser>()
                .SetMemoryAllocator<ArrayPoolMemoryAllocator>()
                .SetCache<PhysicalFileSystemCache>()
                .SetCacheHash<CacheHash>()
                .AddProvider<PhysicalFileSystemProvider>()
                .AddProcessor<ResizeWebProcessor>()
                .AddProcessor<FormatWebProcessor>()
                .AddProcessor<BackgroundColorWebProcessor>();

            // 加载SQL MAP功能
            services.AddCommandPoolService(options => { });

            MaintenanceAdmin.Registe<MaskMaintenanceModel>();
            services.AddBatmanMemoryCache(IocManager.Instance.IocContainer);

            return services.AddAbp<APP_Start.JianbeiForumModule>(options =>
            {
                //options.IocManager.IocContainer.AddFacility<LoggingFacility>(f =>
                //{
                //    f.UseAbpNLog().WithConfig("nlog.config");
                //});
            });
        }

        public void Configure(IApplicationBuilder app,
            IHostingEnvironment env,
            IOptions<SenparcSetting> senparcSetting,
            IOptions<SenparcWeixinSetting> senparcWeixinSetting)
        {
            app.UseAbp();
            app.UseImageSharp(); // It need invoke before UseStatiFile Method
            app.UseStaticFiles();



            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            #region senparc微信配置

            // 启动 CO2NET 全局注册，必须！
            IRegisterService register = RegisterService.Start(env, senparcSetting.Value)
                                                       .UseSenparcGlobal(false, null);

            ////开始注册微信信息，必须！
            register.UseSenparcWeixin(senparcWeixinSetting.Value, senparcSetting.Value);

            #endregion



            app.UseSignalR(routes => routes.MapHub<ChatHub>("/chatHub"));

            app.UseAuthentication();
            app.UseMvc(routesBuilder =>
            {
                routesBuilder.MapAreaRoute(name: RouteNames.Forum, areaName: RouteNames.Forum,
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

                routesBuilder.MapAreaRoute(name: RouteNames.Admin, areaName: RouteNames.Admin,
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

                routesBuilder.MapAreaRoute(name: RouteNames.ChatRoom, areaName: RouteNames.ChatRoom,
                    template: "{area:exists}/{controller=Room}/{action=Index}/{id?}");

                routesBuilder.MapAreaRoute(name: RouteNames.Maintenance, areaName: RouteNames.ChatRoom,
                   template: "{area:exists}/{controller=Room}/{action=Index}/{id?}");


                routesBuilder.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
